﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JXT.PrimaryKey.Batman.Core.Configuration;

namespace JXT.PrimaryKey.Batman.Core.OAuth
{
    /// <summary>
    /// 默认REST方式OAuth认证基类
    /// </summary>
    public abstract class RestAuth : OAuthBase, IRestAuth
    {
        private  readonly Func<NetHttpClient> _httpClientCreater = () => new NetHttpClient();
        private AuthContext _context;
        public AuthContext Context { get { return _context; } }
        private IHttpClient _httpClient;
        public RestAuth(string appKey=null, string signatureKey=null, Func<IHttpClient> httpClientCreater = null)
        {
            if (_context == null)
            {
                _context = new AuthContext(appKey, signatureKey);
            }
            _httpClient = httpClientCreater == null ? _httpClientCreater() : httpClientCreater();
        }


        

        public virtual string GetAuthorizeUri(Uri requestTokeUri,Uri authorizeUri,Uri callback, bool isEnforce = false)
        {
            if (String.IsNullOrEmpty(Context.Token) || String.IsNullOrEmpty(Context.TokenSecret) || isEnforce)
            {
                getRequestToken(requestTokeUri);
            }
            string url = String.Format("{0}?oauth_token={1}&oauth_callback={2}&display=page", authorizeUri, Context.Token, UrlEncode(callback.ToString()));
            return url;
        }

        public void AccessTokenUserId(Uri accessTokeUri,string verifier,string token,string tokensecret)
        {
          
            Context.Verifier = verifier;
            string requestUrl, parameterString;
            string signature = GenerateSignature(accessTokeUri, Context.AppKey, Context.SignatureKey, token,tokensecret, verifier, "GET", GenerateTimeStamp(), GenerateNonce(), out requestUrl, out parameterString);
            parameterString += "&oauth_signature=" + UrlEncode(signature);
            string result = _httpClient.GetRequest(new Uri(String.Format("{0}?{1}", requestUrl, parameterString)));
            if (!String.IsNullOrWhiteSpace(result))
            {
                var array = result.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var item in array)
                {
                    var subArray = item.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    if (subArray.Length != 2)
                        continue;
                    setContext(subArray[0], subArray[1]);
                }
            }
        }

        protected void getRequestToken(Uri requestTokeUri,IDictionary<string,string> parameters=null)
        {
            string requestUrl, parameterString;
            string signature = base.GenerateSignature(requestTokeUri, Context.AppKey, Context.SignatureKey, null, null, null, "GET", GenerateTimeStamp(), GenerateNonce(), out requestUrl, out parameterString, parameters);
            parameterString += "&oauth_signature=" + UrlEncode(signature);
            string result = _httpClient.GetRequest(new Uri(String.Format("{0}?{1}", requestUrl, parameterString)));
            if (!String.IsNullOrWhiteSpace(result))
            {
                var array = result.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var item in array)
                {
                    var subArray = item.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    if (subArray.Length != 2)
                        continue;
                    setContext(subArray[0], subArray[1]);
                }
            }
        }

        private void setContext(string key, string value)
        {
            switch (key)
            {
                case "oauth_token":
                    Context.Token = value;
                    break;
                case "oauth_token_secret":
                    Context.TokenSecret = value;
                    break;
                case "user_id":
                    Context.UserId = value;
                    break;
                case "name":
                    Context.UserId = value;
                    break;
                default:
                    break;
            }
        }

        public string CreateGetUrl(Uri baseUri, IDictionary<string, string> parameters = null)
        {
            string requestUrl, parameterString;
            string signature = GenerateSignature(baseUri, Context.AppKey, Context.SignatureKey, Context.Token, Context.TokenSecret, Context.Verifier, "GET", GenerateTimeStamp(), GenerateNonce(), out requestUrl, out parameterString, parameters);
            parameterString += "&oauth_signature=" + UrlEncode(signature);
            return String.Format("{0}?{1}", baseUri, parameterString);
        }

        public string GetRestResponse(Uri baseUri, IDictionary<string, string> parameters = null)
        {
            string url = CreateGetUrl(baseUri, parameters);
            return _httpClient.GetRequest(new Uri(url));
        }

        public Dictionary<string, string> GetMircoBlogApiAddress()
        {
            var configurationsection = SupernovaConfigurationManager.GetServiceConfigurationSection();
            Dictionary<string, string> mircoDictionary = new Dictionary<string, string>();
            if (configurationsection != null)
            {
                foreach (var item in configurationsection.OauthSetting.ToList())
                {
                    mircoDictionary.Add(item.Name, item.Path);
                }
            }
            return mircoDictionary;
        }

        public void AccessTokenUserId(Uri accessTokeUri, string verifier)
        {
            Context.Verifier = verifier;
            string requestUrl, parameterString;
            string signature = GenerateSignature(accessTokeUri, Context.AppKey, Context.SignatureKey, Context.Token, Context.TokenSecret, verifier, "GET", GenerateTimeStamp(), GenerateNonce(), out requestUrl, out parameterString);
            parameterString += "&oauth_signature=" + UrlEncode(signature);
            string result = _httpClient.GetRequest(new Uri(String.Format("{0}?{1}", requestUrl, parameterString)));
            if (!String.IsNullOrWhiteSpace(result))
            {
                var array = result.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var item in array)
                {
                    var subArray = item.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    if (subArray.Length != 2)
                        continue;
                    setContext(subArray[0], subArray[1]);
                }
            }
        }
    }
}
